From 396acf3bbbe00a192cb0ea0a9ccf91b1d8d2850b Mon Sep 17 00:00:00 2001
From: Fuwn <50817549+Fuwn@users.noreply.github.com>
Date: Sat, 24 Jan 2026 13:09:50 +0000
Subject: Initial commit

Created from https://vercel.com/new
---
 .../[websiteId]/sessions/SessionActivity.tsx       | 94 ++++++++++++++++++++++
 1 file changed, 94 insertions(+)
 create mode 100644 src/app/(main)/websites/[websiteId]/sessions/SessionActivity.tsx

(limited to 'src/app/(main)/websites/[websiteId]/sessions/SessionActivity.tsx')

diff --git a/src/app/(main)/websites/[websiteId]/sessions/SessionActivity.tsx b/src/app/(main)/websites/[websiteId]/sessions/SessionActivity.tsx
new file mode 100644
index 0000000..cbb2810
--- /dev/null
+++ b/src/app/(main)/websites/[websiteId]/sessions/SessionActivity.tsx
@@ -0,0 +1,94 @@
+import {
+  Button,
+  Column,
+  Dialog,
+  DialogTrigger,
+  Heading,
+  Icon,
+  Popover,
+  Row,
+  StatusLight,
+  Text,
+} from '@umami/react-zen';
+import { isSameDay } from 'date-fns';
+import { LoadingPanel } from '@/components/common/LoadingPanel';
+import { useMessages, useMobile, useSessionActivityQuery, useTimezone } from '@/components/hooks';
+import { Eye, FileText } from '@/components/icons';
+import { EventData } from '@/components/metrics/EventData';
+import { Lightning } from '@/components/svg';
+
+export function SessionActivity({
+  websiteId,
+  sessionId,
+  startDate,
+  endDate,
+}: {
+  websiteId: string;
+  sessionId: string;
+  startDate: Date;
+  endDate: Date;
+}) {
+  const { formatMessage, labels } = useMessages();
+  const { formatTimezoneDate } = useTimezone();
+  const { data, isLoading, error } = useSessionActivityQuery(
+    websiteId,
+    sessionId,
+    startDate,
+    endDate,
+  );
+  const { isMobile } = useMobile();
+  let lastDay = null;
+
+  return (
+    <LoadingPanel data={data} isLoading={isLoading} error={error}>
+      <Column gap>
+        {data?.map(({ eventId, createdAt, urlPath, eventName, visitId, hasData }) => {
+          const showHeader = !lastDay || !isSameDay(new Date(lastDay), new Date(createdAt));
+          lastDay = createdAt;
+
+          return (
+            <Column key={eventId} gap>
+              {showHeader && <Heading size="1">{formatTimezoneDate(createdAt, 'PPPP')}</Heading>}
+              <Row alignItems="center" gap="6" height="40px">
+                <StatusLight color={`#${visitId?.substring(0, 6)}`}>
+                  <Text wrap="nowrap">{formatTimezoneDate(createdAt, 'pp')}</Text>
+                </StatusLight>
+                <Row alignItems="center" gap="2">
+                  <Icon>{eventName ? <Lightning /> : <Eye />}</Icon>
+                  <Text wrap="nowrap">
+                    {eventName
+                      ? formatMessage(labels.triggeredEvent)
+                      : formatMessage(labels.viewedPage)}
+                  </Text>
+                  <Text weight="bold" style={{ maxWidth: isMobile ? '400px' : null }} truncate>
+                    {eventName || urlPath}
+                  </Text>
+                  {hasData > 0 && <PropertiesButton websiteId={websiteId} eventId={eventId} />}
+                </Row>
+              </Row>
+            </Column>
+          );
+        })}
+      </Column>
+    </LoadingPanel>
+  );
+}
+
+const PropertiesButton = props => {
+  return (
+    <DialogTrigger>
+      <Button variant="quiet">
+        <Row alignItems="center" gap>
+          <Icon>
+            <FileText />
+          </Icon>
+        </Row>
+      </Button>
+      <Popover placement="right">
+        <Dialog>
+          <EventData {...props} />
+        </Dialog>
+      </Popover>
+    </DialogTrigger>
+  );
+};
-- 
cgit v1.2.3

